ratelimit: add support for x-ratelimit-* headers in local rate limiting#18157
ratelimit: add support for x-ratelimit-* headers in local rate limiting#18157adisuissa merged 56 commits intoenvoyproxy:mainfrom
Conversation
|
CC @envoyproxy/api-shepherds: Your approval is needed for changes made to |
f532236 to
79e0f66
Compare
There was a problem hiding this comment.
looks like you always give init_fill_time = true. Do we need the param in the first place?
There was a problem hiding this comment.
No, in local rate limit network filter, init_fill_time = false. A test of local rate limit network filter will throw an exception for different time system if we initialize fill_time_ in LocalRateLimiterImpl for local rate limit network filter.
There was a problem hiding this comment.
Do we know why this is the case? What is the implication of not initializing the fill time at ctor time?
There was a problem hiding this comment.
Even though this is used for calculating the default per-route RateLimit_Reset which is new header field for HTTP only, I am interested to learn why it fails in network filter? This code seems not to be something HTTP filter specific?
There was a problem hiding this comment.
Ok, it is a mistake, and I suppose it is because I was not not familiar about the time system in the test before.
There is a assert failure threw by the test shows there is an inconsistent time system. And today I find the problem is only in the test code, not in the source code.
But I cannot fix the test. There is a conflict between the MockDispatcher which uses the GlobalTimeSystem and the MockStreamInfo in MockReadFilterCallbacks which uses the SimulatedTimeSystem. Do you have some ideas?
There was a problem hiding this comment.
There is already a TODO(#4160) in class GlobalTimeSystem: Switch default testSystem to SimulatedTimeSystem. I guess switching to that system might resolve the issue? I don't have the context on that TODO though.
If that is a lot of work to do or if that doesn't work, a quick workaround off top of my head (just for ideas not necessary to be the final solution): wrapping this line under if condition like below:
if (!descriptors.empty()) {
tokens_.fill_time_ = time_source_.monotonicTime();
}
This implicitly limits this code path to local descriptor override case which is only available in HTTP filter.
It is a bit hacky workaround :) but, IMO, it is still better than having bool flag in the interface all over the places.
There was a problem hiding this comment.
Unfortunately, I do not think it might work. In fact, a HTTP filter should load time to fill_time_ while its descriptors are empty.
There was a problem hiding this comment.
I Imagine we don't need to have optional here. Do you consider just avoiding push(abls::nullopt)?
There was a problem hiding this comment.
We still need an optional here. In any request the filter is not enabled, we will not attach x-ratelimit-* headers.
adisuissa
left a comment
There was a problem hiding this comment.
Thanks for working on this!
Left an API comment.
There was a problem hiding this comment.
How is this enum different than:
envoy/api/envoy/extensions/filters/http/ratelimit/v3/rate_limit.proto
Lines 28 to 34 in 1aba2de
I think we should use the other enum, and not redefine a new one as this can cause a divergence in the future (e.g., global RL supporting draft 03, while local RL supporting draft 04). We should make this consistent.
There was a problem hiding this comment.
DRAFT_VERSION_03 here means the responding x-ratelimit-* headers are according to draft RFC version 03. I think we should keep its name. And do you think it is a good idea for us to extract XRateLimitHeadersRFCVersion in LocalRateLimit and RateLimit and relocate it in common/ratelimit/v3/ratelimit.proto?
There was a problem hiding this comment.
I don't mind the name DRAFT_VERSION_03.
Yes, I do think it would be better to extract the enum to the extension's common ratelimit proto.
There was a problem hiding this comment.
An API change has been committed, but the CI reports the change is non-backwards-compatible. Is this a issue that needs to be fixed?
There was a problem hiding this comment.
The generated_api_shadow directory was removed in #18091.
Please remove this file
There was a problem hiding this comment.
Ok, recent commits have been merged.
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
adisuissa
left a comment
There was a problem hiding this comment.
Left some API comments.
| "envoy.config.filter.http.rate_limit.v2.RateLimit"; | ||
|
|
||
| // Defines the version of the standard to use for X-RateLimit headers. | ||
| enum XRateLimitHeadersRFCVersion { |
There was a problem hiding this comment.
This should be deprecated.
| // | ||
| // Disabled by default. | ||
| XRateLimitHeadersRFCVersion enable_x_ratelimit_headers = 8 | ||
| common.ratelimit.v3.XRateLimitHeadersRFCVersion enable_x_ratelimit_headers = 8 |
There was a problem hiding this comment.
Unfortunately this breaks backwards compatibility, and therefore the field must be deprecated and a new field with the new type should be introduced.
@htuch extracting the enum to a common place (see: api/envoy/extensions/common/ratelimit/v3/ratelimit.proto) is arguably the right way to go, but will cause some deprecation churn. Another option is to make the local_rate_limit proto use the enum directly from the (global) rate_limit proto. WDYT?
There was a problem hiding this comment.
I think for the local rate limiting, put it in the common location and use it there. Either deprecate or eave a TODO to cleanup for global. I'm not super keen on API dependencies between extensions, since we're creating an unnecessary dependency in build/protos.
There was a problem hiding this comment.
In my opinion, if we treat local rate limit and rate limit as two independent extensions (like if we can decouple envoy and extensions someday in the future), both local rate limit and rate limit should maintain their own enum values. But if we consider the local rate limit and rate limit are inseparable, extract common enum is a good choice.
There was a problem hiding this comment.
My take on this is that similar to the original issue (#15293) that requested a local rate-limiting feature support similar to what the global rate-limiting does, then in the future they should be in-sync.
I think that adding the enum to the common proto (as you've already done) is a good thing, and to avoid changes to the global rate-limiting API (following @htuch suggestion), we should not deprecate this enum at this stage, but add a [#next-major-version: comment (see: example here).
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
|
/retest |
|
Retrying Azure Pipelines: |
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
snowp
left a comment
There was a problem hiding this comment.
Some nits but otherwise this looks good to me
/wait
| : requestAllowedHelper(tokens_); | ||
| } | ||
|
|
||
| uint32_t LocalRateLimiterImpl::maxTokens( |
There was a problem hiding this comment.
We tend to favor longer names if it helps readability, but it's probably ok as is
| *descriptors_.Add()); | ||
| initializeWithDescriptor(std::chrono::milliseconds(3000), 2, 2); | ||
|
|
||
| /// 2 -> 1 tokens |
There was a problem hiding this comment.
Thanks, I will fix it.
|
|
||
| TEST_F(FilterTest, Runtime) { | ||
| setup(fmt::format(config_yaml, "1", "false"), false, false); | ||
| setup(fmt::format(config_yaml, "1", "false", "\"OFF\""), false, false); |
There was a problem hiding this comment.
I don't think you need to include the quotes in there? You don't when you specify the other option
There was a problem hiding this comment.
No, we cannot remove these quotes. We write YAML like
local_rate_limit_per_downstream_connection: false
enable_x_ratelimit_headers: "OFF"
, so we must keep these quotes.
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
|
@adisuissa mind doing the API sign off? |
| // Defines the version of the standard to use for X-RateLimit headers. | ||
| // This field is deprecated in favor of :ref:`XRateLimitHeadersRFCVersion <envoy_v3_api_enum_extensions.common.ratelimit.v3.XRateLimitHeadersRFCVersion>`. | ||
| enum XRateLimitHeadersRFCVersion { | ||
| option deprecated = true; |
There was a problem hiding this comment.
I'm on the fence whether this should be deprecated while enable_x_ratelimit_headers isn't deprecated and a new alternative isn't introduced (that is, both should either be deprecated or not).
I guess that for now you can remove the deprecation, and add #next-major-version to your comment above.
There was a problem hiding this comment.
So, we are going to unify the XRateLimitHeadersRFCVersion used by rate limit and local rate limit. I will change the deprecated to a #next-major-version.
| for (const auto& request_descriptor : request_descriptors) { | ||
| auto it = descriptors_.find(request_descriptor); | ||
| if (it != descriptors_.end()) { | ||
| return static_cast<uint32_t>(absl::ToInt64Seconds( |
There was a problem hiding this comment.
Is there some expected bound to the result of ToInt64Seconds(...)? Could it overflow or cause issues with the cast to uint32_t?
There was a problem hiding this comment.
I have changed the return type from uint32_t to int64_t in previous commits, so we do not need the cast anymore.
Signed-off-by: Xie Zhihao <zhihao.xie@intel.com>
|
/retest |
|
Retrying Azure Pipelines: |
|
@adisuissa could you please reinstate the API approval? |
…ng (envoyproxy#18157) ratelimit: add support for x-ratelimit-* headers in local rate limiting Signed-off-by: Xie Zhihao <zhihao.xie@intel.com> Signed-off-by: kuochunghsu <kuochunghsu@pinterest.com>
Signed-off-by: Xie Zhihao zhihao.xie@intel.com
Commit Message: ratelimit: add support for x-ratelimit-* headers in local rate limiting
Additional Description:
Risk Level: Low
Testing: Unit
Docs Changes: N/A
Release Notes: Added
Platform Specific Features: N/A
Fixes #15293
Deprecated: the envoy::extensions::filters::http::ratelimit::v3::RateLimit::XRateLimitHeadersRFCVersion is deprecated in favor of envoy::extensions::common::ratelimit::v3::XRateLimitHeadersRFCVersion